package com.zsk.mqtt.app;

import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import com.alibaba.fastjson.JSON;

public class MqttUI extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    protected SimpleDateFormat fmt = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");

    /**
     * 订阅列表
     */
    protected List<String> topics = new ArrayList<String>() {
        /**
         *
         */
        private static final long serialVersionUID = 1L;

        {
            add("/niiam/device/dlpf2/info/+");
        }
    };

    // 发布消息框
    protected JTextField txtSendMSg;
    // 发布消息框
    protected JTextField txtSendTopic;
    // 发布消息
    protected JButton btnSend;
    // 订阅主题框
    protected JTextField txtSubTopic;
    // 订阅主题
    protected JButton btnSub;
    // 取消订阅主题
    protected JButton btnUnsub;
    // 日志
    protected JTextArea txtLog;
    // 订阅接受到的消息
    protected JTextArea txtSubMsg;

    protected Mqtt.StateListener subListener;

    protected Mqtt app;

    protected String clientId;

    protected Thread retryHandler;

    public MqttUI() {
        setSize(1000, 600);
        setLocationRelativeTo(null);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridLayout rootLayout = new GridLayout(1, 3);
        setLayout(rootLayout);
        btnSend = new JButton("发布");
        txtSubTopic = new JTextField(20);
        txtSendMSg = new JTextField(20);
        txtSendTopic = new JTextField(20);
        btnSub = new JButton("订阅");
        btnUnsub = new JButton("取消订阅");
        txtLog = new JTextArea(15, 500);
        txtSubMsg = new JTextArea(15, 500);

        // clientId = "app-" + UUID.randomUUID().toString().replaceAll("-", "");
        clientId = "device-uv-test-device";
        setTitle(clientId);

        subListener = new Mqtt.StateListener() {

            @Override
            public void messageArrived(String topic, MqttMessage message) {
                recLog("接收到新消息：" + "qos:" + message.getQos() + ",msg:" + new String(message.getPayload()));

            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                // 发布消息送达到

            }

            @Override
            public void connectionLost(Throwable cause) {
                uiLog("连接已断开");
                reconnect();

            }

            @Override
            public void connectComplete(boolean reconnect, String serverURI) {

                uiLog("连接完成" + reconnect);
                subscribeDefaultTopic();

            }

        };

        app = new Mqtt(clientId, subListener);

        JPanel leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

        JPanel subPanel = new JPanel(new GridLayout(5, 1));
        subPanel.add(new JLabel("订阅主题======================"));
        subPanel.add(txtSubTopic);
        subPanel.add(btnSub);
        subPanel.add(btnUnsub);
        leftPanel.add(subPanel);

        JPanel sendPanel = new JPanel(new GridLayout(10, 1));
        sendPanel.add(new JLabel("发布信息======================"));
        sendPanel.add(new JLabel("发布主题"));
        sendPanel.add(txtSendTopic);
        sendPanel.add(new JLabel("信息"));
        sendPanel.add(txtSendMSg);
        sendPanel.add(btnSend);
        leftPanel.add(sendPanel);

        add(leftPanel);

        add(new JScrollPane(txtLog));

        add(new JScrollPane(txtSubMsg));

        setVisible(true);
    }

    protected void connect() {

        try {
            app.connect();
            uiLog("连接成功");
            return;
        } catch (MqttException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            uiLog("连接失败，" + e.toString());
        }
        reconnect();
    }

    protected void reconnect() {
        if (retryHandler != null) {
            return;
        }
        retryHandler = new Thread(() -> {
            int retryTime = 0;
            while (true) {

                retryTime++;
                if (retryTime > 10000) {
                    uiLog("已经尝试重连" + retryTime + "次，停止重试");
                    break;
                }
                uiLog("正在尝试重连..." + retryTime);

                try {
                    if (app.isConnected()) {
                        uiLog("尝试重新连接成功");
                        // 非永久订阅重连后要重新订阅
                        for (String topic : topics) {
                            app.subscribe(topic, 0);
                        }
                        retryHandler = null;
                        break;
                    }
                    app.reconnect();
                } catch (Exception e) {
                    uiLog("第" + retryTime + "次尝试重新连接失败，" + e.toString());
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        retryHandler.start();
    }

    protected synchronized void uiLog(Object o) {
        String mString = fmt.format(new Date()) + ": " + o + "\n";
        txtLog.append(mString);
    }

    protected synchronized void recLog(Object o) {
        String mString = fmt.format(new Date()) + ": " + o + "\n";
        txtSubMsg.append(mString);
    }

    protected void initEvent() {
        txtSendTopic.setText("/niiam/device/uv/info/id");
        txtSubTopic.setText(txtSendTopic.getText());
        txtSendMSg.setText("test");

        txtSubMsg.setText("订阅信息\n");

        // 发布消息
        btnSend.addActionListener(e -> {
            try {
                String msg = txtSendMSg.getText();
                app.publish(txtSendTopic.getText(), msg, 0, false);
                uiLog("发送" + msg + "成功");
            } catch (MqttException e1) {
                e1.printStackTrace();
                uiLog("发送失败" + e1.toString());
            }

        });

        // 订阅消息
        btnSub.addActionListener(e -> {
            String topic = txtSubTopic.getText();
            try {
                app.subscribe(topic, 0);
                uiLog("订阅 " + topic + " 成功");
            } catch (MqttException e1) {
                e1.printStackTrace();
                uiLog("订阅 " + topic + " 失败 " + e1.toString());
            }
        });
        // 取消订阅消息
        btnUnsub.addActionListener(e -> {
            String topic = txtSubTopic.getText();
            try {
                app.unsubscribe(topic);
                uiLog("取消订阅 " + topic + " 成功");
            } catch (MqttException e1) {
                e1.printStackTrace();
                uiLog("取消订阅 " + topic + " 失败 " + e1.toString());
            }
        });
    }

    private void subscribeDefaultTopic() {
        for (String topic : topics) {
            try {
                app.subscribe(topic, 0);
                uiLog("订阅" + topic + "成功");
            } catch (MqttException e) {
                uiLog("订阅" + topic + "失败");
                e.printStackTrace();
            }
        }

    }

    boolean start = false;

    public void theadPublish() {
        if (start) {
            return;
        }
        ModelInfo info = new ModelInfo();

        int totalLay = 200;
        info.setName("loveCat");
        info.setPrintPercent(10);
        info.setState("running");
        info.setCurrentLayer(1);
        info.setTotalLayer(totalLay);
        info.setCurLayerRemTime(60);
        info.setToalTime(getTimeStr(200));
        info.setRemainingTime("01:03:25");
        new Thread(() -> {
            int index = 1;
            while (true) {
                try {
                    info.setCurrentLayer(index);
                    info.setPrintPercent((int)(index * 1.0 / 200 * 100));
                    info.setPastTime(getTimeStr(index));
                    info.setRemainingTime(getTimeStr(totalLay - index));
                    String str = JSON.toJSONString(info);
                    app.publish("/niiam/device/uv/info/test-device", str, 0, false);
                    // System.out.println("发送："+str);
                } catch (MqttException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                index++;
                if (index > 200) {
                    index = 1;
                }
            }
        }).start();

    }

    public static int[] getTime(int lay) {
        int[] hm = new int[3];
        int hs = 3600;
        int totalSeconds = 60 * lay;
        if (totalSeconds < 60) {
            hm[0] = 0;
            hm[1] = 0;
            hm[2] = totalSeconds;
        } else if (totalSeconds < hs) {
            int m = (int)(totalSeconds / 60.0);
            hm[0] = 0;
            hm[1] = m;
            hm[2] = (totalSeconds - 60 * m);
        } else {
            int h = totalSeconds / hs;
            int m = (int)((totalSeconds - hs * h) / 60.0);
            hm[0] = h;
            hm[1] = m;
            hm[2] = (totalSeconds - hs * h - 60 * m);
        }
        return hm;
    }

    public static String getTimeStr(int lay) {
        int[] time = getTime(lay);
        String timeStr = String.format("%02d", time[0]) + ":" + String.format("%02d", time[1]) + ":"
            + String.format("%02d", time[2]);;
        return timeStr;
    }

    public static void main(String[] args) {
        MqttUI appUI = new MqttUI();
        appUI.initEvent();
        appUI.connect();
        appUI.theadPublish();
    }
}
